package cn.atcoder.air.server;

import cn.atcoder.air.config.ProviderConfig;
import cn.atcoder.air.config.ProviderFactory;
import cn.atcoder.air.exception.ConnectAuthException;
import cn.atcoder.air.msg.*;
import cn.atcoder.air.transport.ClientTransportFactory;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * @author yangjunda1
 * @description
 * @date 5/9/19 4:46 PM
 */
public class ServerChannelHandler extends SimpleChannelInboundHandler<BaseMessage> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerChannelHandler.class);

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //channel失效，从Map中移除
        LOGGER.error("Channel " + ctx.channel().remoteAddress().toString() + " has been closed");
        ServerChannelFactory.remove((SocketChannel)ctx.channel());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("---" + ctx.channel().remoteAddress() + "正在活跃---");
    }
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, BaseMessage baseMessage) throws Exception {
        Channel channel = channelHandlerContext.channel();
        MessageType messageType = baseMessage.getMessageType();
        switch (messageType) {
            case HEARTBEAT_REQUEST_MSG:
                HeartbeatResponseMessage msg = MessageBuilder.buildHeartbeatResponse(baseMessage);
                channel.writeAndFlush(msg);
                break;
            case CALLBACK_REQUEST_MSG:
                CallbackRequestMessage callbackRequestMessage = (CallbackRequestMessage) baseMessage;
                String clazzName = callbackRequestMessage.getClazzName();
                if (!ProviderFactory.contains(clazzName)) {
                    CallbackResponseMessage responseMessage = MessageBuilder.buildNoProviderCallbackResponse(callbackRequestMessage);
                    channelHandlerContext.channel().writeAndFlush(responseMessage);
                } else {
                    final CallbackResponseMessage responseMessage = MessageBuilder.buildCallbackResponse(baseMessage);
                    ProviderConfig providerConfig = ProviderFactory.getProvider(clazzName);
                    Method method = providerConfig.getMethod(callbackRequestMessage.getMethodName());
                    Object result = method.invoke(providerConfig.refer(), callbackRequestMessage.getArgs());
                    responseMessage.setBody(result);
                    channelHandlerContext.channel().writeAndFlush(responseMessage);
                }

                break;
            case HEARTBEAT_RESPONSE_MSG:
                break;
            case CALLBACK_RESPONSE_MSG:
                ClientTransportFactory.refer().receiveResponse((ResponseMessage) baseMessage);
                break;
            default:break;
        }
        ReferenceCountUtil.release(baseMessage);
    }

}
